package zhoug.chart.charts;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.github.mikephil.charting.charts.RadarChart;
import com.github.mikephil.charting.components.IMarker;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.data.RadarData;
import com.github.mikephil.charting.data.RadarDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.renderer.DataRenderer;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Utils;
import zhoug.chart.Chart2Sdk;
import zhoug.chart.core.styleconfig.IMPRadarStyleConfig;
import zhoug.chart.core.styleconfig.MPRadarStyleConfig;
import zhoug.chart.data.HkChartData;
import zhoug.chart.data.MPRadarChartDataCreator;
import zhoug.chart.data.OnDateSetCreateListener;
import zhoug.chart.formatters.MPAxisTextValueFormatter;
import zhoug.chart.formatters.MPDataSetValueFormatter;
import zhoug.chart.ints.IMPChartPlaceholder;
import zhoug.chart.renderer.MPRadarChartRenderer;
import zhoug.chart.renderer.MPRadarChartXAxisRenderer;
import zhoug.logging.Logger;

import java.util.List;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;

/**
 * 雷达图
 *
 * @Author: zhoug
 * @Date: 2024-01-30
 * @Description:
 */
public class MPRadarChart extends RadarChart  implements IMPChart<RadarData, IMPRadarStyleConfig> {
    private static final boolean DEBUG= Chart2Sdk.isDebug();
    protected MPChartHelper mChartHelper;
    protected IMPRadarStyleConfig mStyleConfig;
    protected String mKey;
    protected OnDateSetCreateListener<RadarDataSet> mOnDateSetCreateListener;
    protected ValueFormatter mDataSetValueFormatter;

    public MPRadarChart(Context context) {
        this(context, null);
    }

    public MPRadarChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MPRadarChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mChartHelper = new MPChartHelper(this, context, attrs, defStyle);
        mStyleConfig = new MPRadarStyleConfig();
        XAxis xAxis = getXAxis();
        MPAxisTextValueFormatter axisTextValueFormatter = new MPAxisTextValueFormatter();
        axisTextValueFormatter.setMinValue(0);
        xAxis.setValueFormatter(axisTextValueFormatter);
        setAnimateDirection(ANIM_DIRECTION_Y);
        mDataSetValueFormatter=new MPDataSetValueFormatter();

    }

    @Override
    protected void init() {
        super.init();
        mXAxisRenderer = new MPRadarChartXAxisRenderer(mViewPortHandler, mXAxis, this);
        mRenderer=new MPRadarChartRenderer(this,getAnimator(),getViewPortHandler());
        mLogEnabled = Chart2Sdk.isDebug();
    }

    @Override
    public void setData(RadarData data) {
        if (data != null && getMarker() != null) {
            highlightValue(null);
        }
        super.setData(data);
    }


    @Override
    public void setData1(RadarData data) {
        if (data != null) {
            setData(data);
            notifyDataSetChanged();
            postInvalidate();
            mChartHelper.animate();
        } else {
            empty();
        }
    }
    /**
     * 设置数据
     *
     * @param list
     */
    @Override
    public void setHkChartData(List<HkChartData> list) {
        MPRadarChartDataCreator creator = new MPRadarChartDataCreator(mStyleConfig);
        creator.setDataSetValueFormatter(mDataSetValueFormatter);
        creator.setOnDateSetCreateListener(mOnDateSetCreateListener);
        RadarData data = creator.crateRadarData(list, mKey);
        MPAxisTextValueFormatter axisTextValueFormatter = getAxisTextValueFormatter();
        if (axisTextValueFormatter != null) {
            axisTextValueFormatter.setValueTexts(creator.getXLabels());
        }
        setData1(data);
    }

    public void setKey(String key) {
        this.mKey = key;
    }

    public void setDataSetValueFormatter(ValueFormatter dataSetValueFormatter) {
        this.mDataSetValueFormatter = dataSetValueFormatter;
    }

    public void setOnDateSetCreateListener(OnDateSetCreateListener<RadarDataSet> onDateSetCreateListener) {
        this.mOnDateSetCreateListener = onDateSetCreateListener;
    }

    /**
     * 获取x轴数据格式化器
     *
     * @return
     */
    @Override
    public MPAxisTextValueFormatter getAxisTextValueFormatter() {
        return mChartHelper.getAxisTextValueFormatter();
    }

    /**
     * 是否绘制数据顶部连接线
     * @param drawLine
     */
    public void setDrawLine(boolean drawLine){
        DataRenderer renderer = getRenderer();
        if(renderer instanceof MPRadarChartRenderer){
            MPRadarChartRenderer mRadarChartRenderer= (MPRadarChartRenderer) renderer;
            mRadarChartRenderer.setDrawLine(drawLine);
        }
    }


    /**
     * 是否绘制网格填充
     * @param drawWebFill
     */
    public void setDrawWebFill(boolean drawWebFill) {
        DataRenderer renderer = getRenderer();
        if(renderer instanceof MPRadarChartRenderer){
            MPRadarChartRenderer mRadarChartRenderer= (MPRadarChartRenderer) renderer;
            mRadarChartRenderer.setDrawWebFill(drawWebFill);
        }
    }

    /**
     * 绘制网格填充色
     * @param color
     */
    public void setWebFillColor(@ColorInt int color){
        DataRenderer renderer = getRenderer();
        if(renderer instanceof MPRadarChartRenderer){
            MPRadarChartRenderer mRadarChartRenderer= (MPRadarChartRenderer) renderer;
            mRadarChartRenderer.setWebFillColor(color);
        }
    }


    @Override
    public void setStyleConfig(@NonNull IMPRadarStyleConfig styleConfig) {
        this.mStyleConfig = styleConfig;
    }

    @NonNull
    @Override
    public IMPRadarStyleConfig getStyleConfig() {
        return this.mStyleConfig;
    }

    /**
     * x轴开始的最小值
     *
     * @return
     */
    @Override
    public int getStartXValue() {
        return mChartHelper.getStartXValue();
    }
    @Override
    public void setChartPlaceholder(IMPChartPlaceholder chartPlaceholder) {
        mChartHelper.setChartPlaceholder(chartPlaceholder);
    }
    /**
     * 暂无数据
     */
    @Override
    public void empty() {
        mChartHelper.empty();
    }

    /**
     * 数据加载失败
     */
    @Override
    public void error() {
        mChartHelper.error();
    }

    /**
     * 重置占位图
     */
    @Override
    public void resetPlaceholder() {
        mChartHelper.resetPlaceholder();
    }

    /**
     * 占位图是否启用
     *
     * @param enable
     * @return
     */
    @Override
    public void setPlaceholderEnable(boolean enable) {
        mChartHelper.setPlaceholderEnable(enable);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        try {
            super.onDraw(canvas);
            mChartHelper.drawPlaceImage(canvas);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        mChartHelper.onLayout();
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mChartHelper.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    /**
     * 不缩放,x,y的scale重置为1
     */
    @Override
    public void zoomNotScale() {
        mChartHelper.zoomNotScale();
    }

    @Override
    public void zoom(float scaleX, float scaleY, float x, float y) {

    }

    /***
     * {@link #ANIM_DIRECTION_X,#ANIM_DIRECTION_Y,#ANIM_DIRECTION_XY}
     * @param animDirection
     */
    @Override
    public void setAnimateDirection(int animDirection) {
        mChartHelper.setAnimateDirection(animDirection);
    }

    /**
     * {@link #ANIM_DIRECTION_X,#ANIM_DIRECTION_Y,#ANIM_DIRECTION_XY}
     */
    @Override
    public int getAnimateDirection() {
        return mChartHelper.getAnimateDirection();
    }

    @Override
    public void setMarker(IMarker marker) {
        super.setMarker(marker);
        mChartHelper.setMarker(marker);
    }

    /**
     * 雷达图区域的大小测量,解决雷达图当文字太长时图表被压制的很小的问题
     */
    @Override
    public void calculateOffsets() {
//        super.calculateOffsets();
        float legendLeft = 0f, legendRight = 0f, legendBottom = 0f, legendTop = 0f;

        if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) {

            float fullLegendWidth = Math.min(mLegend.mNeededWidth,
                    mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent());

            switch (mLegend.getOrientation()) {
                case VERTICAL: {
                    float xLegendOffset = 0.f;

                    if (mLegend.getHorizontalAlignment() == Legend.LegendHorizontalAlignment.LEFT
                            || mLegend.getHorizontalAlignment() == Legend.LegendHorizontalAlignment.RIGHT) {
                        if (mLegend.getVerticalAlignment() == Legend.LegendVerticalAlignment.CENTER) {
                            // this is the space between the legend and the chart
                            final float spacing = Utils.convertDpToPixel(13f);

                            xLegendOffset = fullLegendWidth + spacing;

                        } else {
                            // this is the space between the legend and the chart
                            float spacing = Utils.convertDpToPixel(8f);

                            float legendWidth = fullLegendWidth + spacing;
                            float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax;

                            MPPointF center = getCenter();

                            float bottomX = mLegend.getHorizontalAlignment() ==
                                    Legend.LegendHorizontalAlignment.RIGHT
                                    ? getWidth() - legendWidth + 15.f
                                    : legendWidth - 15.f;
                            float bottomY = legendHeight + 15.f;
                            float distLegend = distanceToCenter(bottomX, bottomY);

                            MPPointF reference = getPosition(center, getRadius(),
                                    getAngleForPoint(bottomX, bottomY));

                            float distReference = distanceToCenter(reference.x, reference.y);
                            float minOffset = Utils.convertDpToPixel(5f);

                            if (bottomY >= center.y && getHeight() - legendWidth > getWidth()) {
                                xLegendOffset = legendWidth;
                            } else if (distLegend < distReference) {

                                float diff = distReference - distLegend;
                                xLegendOffset = minOffset + diff;
                            }

                            MPPointF.recycleInstance(center);
                            MPPointF.recycleInstance(reference);
                        }
                    }

                    switch (mLegend.getHorizontalAlignment()) {
                        case LEFT:
                            legendLeft = xLegendOffset;
                            break;

                        case RIGHT:
                            legendRight = xLegendOffset;
                            break;

                        case CENTER:
                            switch (mLegend.getVerticalAlignment()) {
                                case TOP:
                                    legendTop = Math.min(mLegend.mNeededHeight,
                                            mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent());
                                    break;
                                case BOTTOM:
                                    legendBottom = Math.min(mLegend.mNeededHeight,
                                            mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent());
                                    break;
                            }
                            break;
                    }
                }
                break;

                case HORIZONTAL:
                    float yLegendOffset = 0.f;

                    if (mLegend.getVerticalAlignment() == Legend.LegendVerticalAlignment.TOP ||
                            mLegend.getVerticalAlignment() == Legend.LegendVerticalAlignment.BOTTOM) {

                        // It's possible that we do not need this offset anymore as it
                        //   is available through the extraOffsets, but changing it can mean
                        //   changing default visibility for existing apps.
                        float yOffset = getRequiredLegendOffset();

                        yLegendOffset = Math.min(mLegend.mNeededHeight + yOffset,
                                mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent());

                        switch (mLegend.getVerticalAlignment()) {
                            case TOP:
                                legendTop = yLegendOffset;
                                break;
                            case BOTTOM:
                                legendBottom = yLegendOffset;
                                break;
                        }
                    }
                    break;
            }

            legendLeft += getRequiredBaseOffset();
            legendRight += getRequiredBaseOffset();
            legendTop += getRequiredBaseOffset();
            legendBottom += getRequiredBaseOffset();
        }

        float minOffsetH = Utils.convertDpToPixel(mMinOffset);
        float minOffsetTop = Utils.convertDpToPixel(mMinOffset);
        float minOffsetBottom = Utils.convertDpToPixel(mMinOffset);
        if (DEBUG) {
            Logger.d(LOG_TAG, "calculateOffsets:minOffsetH=" + minOffsetH + ",minOffsetTop=" + minOffsetTop+ ",minOffsetBottom=" + minOffsetBottom);
        }

        XAxis x = this.getXAxis();
        if (x.isEnabled() && x.isDrawLabelsEnabled()) {
            minOffsetH = Math.max(minOffsetH, x.mLabelRotatedWidth);
            minOffsetTop = Math.max(minOffsetTop, x.mLabelHeight*2);
            minOffsetBottom = Math.max(minOffsetBottom, x.mLabelHeight*2);
        }
        if (DEBUG) {
            Logger.d(LOG_TAG, "calculateOffsets:minOffsetH=" + minOffsetH + ",minOffsetTop=" + minOffsetTop+ ",minOffsetBottom=" + minOffsetBottom);
        }

        legendTop += getExtraTopOffset();
        legendRight += getExtraRightOffset();
        legendBottom += getExtraBottomOffset();
        legendLeft += getExtraLeftOffset();

        if (mLogEnabled)
            if (DEBUG) {
                Logger.d(LOG_TAG, "legendTop: " + legendTop + ", legendRight: " + legendRight
                        + ", legendBottom: " + legendBottom + ", legendLeft: " + legendLeft);
            }


        float offsetLeft = Math.max(minOffsetH, legendLeft);
        float offsetTop = Math.max(minOffsetTop, legendTop);
        float offsetRight = Math.max(minOffsetH, legendRight);
        float offsetBottom = Math.max(minOffsetBottom,  legendBottom);
        mViewPortHandler.restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom);

        if (mLogEnabled && DEBUG)
            Logger.d(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop
                    + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom);

    }

}
